package com.xssq.mvc;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xssq.mvc.impl.DefaultHandlerInvoker;
import com.xssq.mvc.impl.DefaultHandlerMapping;
import com.xssq.mvc.impl.DefaultViewResolver;

@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = -6894230716377775590L;
	
	private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
	
	private HandlerMapping mapping = new DefaultHandlerMapping();
	private HandlerInvoker invoker = new DefaultHandlerInvoker();
	private ViewResolver resolver = new DefaultViewResolver();
	

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		// 初始化控制器映射解析
		ControllerResovler.resolve();
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 设置编码
		req.setCharacterEncoding("UTF-8");
		// 获取请求方法和请求路径
		String requestMethod = req.getMethod();
		String requestPath = req.getServletPath() + StringUtils.defaultIfEmpty(req.getPathInfo(), "");
		logger.debug("收到请求 ==> [{}] {}", requestMethod, requestPath);
		// 根据请求方法和请求路径获取对应handler
		Handler handler = mapping.getHandler(requestMethod, requestPath);
		// 判断对应handler是否存在，不存在直接返回404
		if (null == handler) {
			//response 404
			resp.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}
		// 保存request和response对象，以便控制器调用
		HttpContext.init(req, resp);
		try {
			// 调用对应handler，里面调用了对应的Controller方法，传递参数
			Object result = invoker.invokeHandler(handler);
			// 根据控制器方法返回值，解析视图逻辑
			resolver.resolve(result);
		} catch (Exception e) {
			// 简单的处理控制器方法调用抛出的异常
			resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
		}
	}
}
